package lab_2;

import com.sun.messaging.ConnectionConfiguration;
import com.sun.messaging.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Connection;
import javax.jms.Session;
import javax.jms.MessageProducer;
import javax.jms.TextMessage;
import javax.jms.ObjectMessage;
import javax.jms.MessageConsumer;
import javax.jms.JMSException;
import javax.jms.MapMessage;
import javax.jms.MessageFormatException;
import java.util.Date;

/**
 *
 * @author grp02 - Pascal Charreix and Meike Paetz
 *
 * This is the SmartTours JMS client which acts as both sender and receiver.
 * It sends a message with the invoice to the agency via the grp02AgencyQueue
 * as an ObjectMessage.
 */
public class SmartToursClient {

    private Connection connectionTravelAgency;
    private Session sessionTravelAgency;
    private MessageProducer producerTravelAgency;
    private MessageConsumer consumerTravelAgency;
    private Connection connectionServiceOperator;
    private Session sessionServiceOperator;
    private MessageProducer producerServiceOperator;
    private boolean running;

    /**
     *
     * The main sends two messages (Text and MapMessage) to the ServiceOperator
     * and logs it to the console.
     */
    public static void main(String[] args) {
        Invoice invoice = new Invoice((int) (Math.random() * 100), "CustomerName", "AgencyName", (int) (Math.random() * 100), (float) (Math.random() * 10000), new Date(System.currentTimeMillis()));
        SmartToursClient smartToursClient = new SmartToursClient();
        smartToursClient.sendTravelAgencyMessage(invoice);
        smartToursClient.sendServiceOperatorMessage("Package reserved");
        smartToursClient.sendServiceOperatorMessage(invoice);
        smartToursClient.receiveTravelAgencyMessage();
        while (smartToursClient.isRunning()) {
            try {
                Thread.currentThread().sleep(1000);
            } catch (InterruptedException ie) {
                System.out.println("Sleep Exception: " + ie.toString());
            }
        }
        smartToursClient.close();
    }

    /**
     *
     * SmartToursClient Constructor
     */
    public SmartToursClient() {
        setupTravelAgencyConnection();
        setupServiceOperatorConnection();
        running = true;
    }

    /**
     *
     * stops client
     */
    public void stop() {
        running = false;
    }

    /**
     *
     * runs client
     */
    public boolean isRunning() {
        return running;
    }

    /**
     *
     * receives TravelAgency message anonymously
     */
    public void receiveTravelAgencyMessage() {
        try {
            Listener listener = new Listener(this);
            consumerTravelAgency.setMessageListener(listener);
            connectionTravelAgency.start();
        } catch (JMSException e) {
            System.err.println("JMS exception occurred: " + e.toString());
        }
    }

    /**
     *
     * closes connection
     */
    public void close() {
        if (connectionTravelAgency != null) {
            try {
                connectionTravelAgency.close();
            } catch (JMSException e) {
                System.err.println("Exception occurend while closing connection: " + e.toString());
            }
        }
        if (connectionServiceOperator != null) {
            try {
                connectionServiceOperator.close();
            } catch (JMSException e) {
                System.err.println("Exception occurend while closing connection: " + e.toString());
            }
        }
    }

    /**
     *
     * sends TravelAgency message invoice
     */
    public void sendTravelAgencyMessage(Invoice invoice) {
        try {
            ObjectMessage objectMessage = sessionTravelAgency.createObjectMessage();
            objectMessage.setObject(invoice);
            System.out.println("Sending object message: " + ((Invoice) objectMessage.getObject()).getInvoiceInformation());
            producerTravelAgency.send(objectMessage);
        } catch (MessageFormatException e) {
            System.err.println("Object deserialization failed: " + e.toString());
        } catch (JMSException e) {
            System.err.println("JMS exception occurred: " + e.toString());
        }
    }

    /**
     *
     * sends ServiceOperator message
     */
    public void sendServiceOperatorMessage(String msg) {
        try {
            TextMessage textMessage = sessionServiceOperator.createTextMessage();
            textMessage.setText(msg);
            System.out.println("Sending text message: " + textMessage.getText());
            producerServiceOperator.send(textMessage);
        } catch (MessageFormatException e) {
            System.err.println("Object deserialization failed: " + e.toString());
        } catch (JMSException e) {
            System.err.println("JMS exception occurred: " + e.toString());
        }
    }

    /**
     *
     * sends ServiceOperator message invoice for payment callback
     */
    public void sendServiceOperatorPaymentCallBack(Invoice invoice) {
        try {
            MapMessage mapMessage = sessionServiceOperator.createMapMessage();
            mapMessage.setInt("HolidayPackageID", invoice.getHolidayPackageID());
            mapMessage.setString("CustomerName", invoice.getCustomerName());
            mapMessage.setFloat("Paid", invoice.getPrice() / 3);
            System.out.println("Sending map message : " + String.valueOf(mapMessage.getInt("HolidayPackageID")) + ", " + mapMessage.getString("CustomerName") + ", " + mapMessage.getFloat("Paid"));
            producerServiceOperator.send(mapMessage);
        } catch (MessageFormatException e) {
            System.err.println("Object deserialization failed: " + e.toString());
        } catch (JMSException e) {
            System.err.println("JMS exception occurred: " + e.toString());
        }
    }

    /**
     *
     * sends ServiceOperator message invoice
     */
    public void sendServiceOperatorMessage(Invoice invoice) {
        try {
            MapMessage mapMessage = sessionServiceOperator.createMapMessage();
            mapMessage.setInt("HolidayPackageID", invoice.getHolidayPackageID());
            mapMessage.setString("DueDate", invoice.getPaymentDate().toString());
            mapMessage.setString("TravelAgencyName", invoice.getTravelAgencyName());
            System.out.println("Sendig map message : " + String.valueOf(mapMessage.getInt("HolidayPackageID")) + ", " + mapMessage.getString("DueDate") + ", " + mapMessage.getString("TravelAgencyName"));
            producerServiceOperator.send(mapMessage);
        } catch (MessageFormatException e) {
            System.err.println("Object deserialization failed: " + e.toString());
        } catch (JMSException e) {
            System.err.println("JMS exception occurred: " + e.toString());
        }
    }

    /**
     *
     * sets up TravelAgency connection
     */
    private void setupTravelAgencyConnection() {
        ConnectionFactory connectionFactory = null;
        Destination destProd = null;
        Destination destConsum = null;
        final String host = "192.168.6.127";
        try {
            connectionFactory = new com.sun.messaging.ConnectionFactory();
            connectionFactory.setProperty(ConnectionConfiguration.imqAddressList, host + ":7676");
        } catch (JMSException e) {
            System.err.println("Error creating connection factory: " + e.toString());
            System.exit(1);
        }
        try {
            destProd = (Destination) new com.sun.messaging.Queue("grp02AgencyQueue");
            destConsum = (Destination) new com.sun.messaging.Queue("grp02SmartToursQueue");
        } catch (JMSException e) {
            System.err.println("Error creating queue or setting destination: " + e.toString());
            System.exit(1);
        }
        try {
            connectionTravelAgency = connectionFactory.createConnection();
            sessionTravelAgency = connectionTravelAgency.createSession(false, Session.AUTO_ACKNOWLEDGE);
            producerTravelAgency = sessionTravelAgency.createProducer(destProd);
            consumerTravelAgency = sessionTravelAgency.createConsumer(destConsum);
        } catch (JMSException e) {
            System.err.println("Error creating connection, session or producer: " + e.toString());
        }
    }

    /**
     *
     * sets up ServiceOperator connection
     */
    private void setupServiceOperatorConnection() {
        ConnectionFactory connectionFactory = null;
        Destination dest = null;
        final String host = "localhost";
        try {
            connectionFactory = new com.sun.messaging.ConnectionFactory();
            connectionFactory.setProperty(ConnectionConfiguration.imqAddressList, host + ":7676");
        } catch (JMSException e) {
            System.err.println("Error creating connection factory: " + e.toString());
            System.exit(1);
        }
        try {
            dest = (Destination) new com.sun.messaging.Queue("grp02OperatorQueue");
        } catch (JMSException e) {
            System.err.println("Error creating queue or setting destination: " + e.toString());
            System.exit(1);
        }
        try {
            connectionServiceOperator = connectionFactory.createConnection();
            sessionServiceOperator = connectionServiceOperator.createSession(false, Session.AUTO_ACKNOWLEDGE);
            producerServiceOperator = sessionServiceOperator.createProducer(dest);
        } catch (JMSException e) {
            System.err.println("Error creating connection, session or producer: " + e.toString());
        }
    }
}
